package com.cimstech.connect;

import com.cimstech.model.*;
import monfox.stack.iec61850.api.*;
import monfox.stack.iec61850.api.client.*;
import monfox.stack.iec61850.api.file.FileService;
import monfox.stack.iec61850.api.types.DataValue;
import monfox.stack.iec61850.api.types.OptFlds;
import monfox.stack.iec61850.api.types.TrgOps;

import java.util.*;

/**
 * Created by dyzhu on 2015/12/10.
 */
public class Execute {
    private static final int integrityPeroid = 300000;
    private static Map<String, Node> nodes = new HashMap<String, Node>();

    public static void execute(String task, String query, IEC61850Client client, IECResult result) throws SCADAException, ModelValueException, ACSIServiceErrorException, ModelCommunicationException, ModelServiceException {
        switch (task) {
        case Commands.READ:
            if (query == null) {
                Execute.readAllDs(client, (Values) result);
            } else {
                Execute.read(query, client, (Values) result);
            }
            break;
        case Commands.ENABLE_BRCB:
            Execute.enableBRCB(client);
            break;
        case Commands.ENABLE_URCB:
            Execute.enableURCB(client);
            break;
        case Commands.DISABLE_BRCB:
            Execute.disableBRCB(client);
            break;
        case Commands.DISABLE_URCB:
            Execute.disableURCB(client);
            break;
        default:
        }
    }

    /**
     * 启用模拟量自动上送
     *
     * @param client
     * @throws SCADAException
     */
    private static void enableBRCB(IEC61850Client client) throws SCADAException {
        try {
            for (LD ld : client.getLDs()) {
                List<BRCB> brcb_list = ld.getLLN0().getBRCBs();
                for (BRCB brcb : brcb_list) {
                    if (!brcb.isReportEnabled()) {
                        // -- not reserved, lets reserve this one
                        try {
                            BRCB.SetOp set_op = brcb.newSetOp();
                            set_op.setBufferTime(1000);
                            set_op.setReservationTime(5000);
                            set_op.setIntegrityPeriod(30000);
                            set_op.setTriggerOptions(TrgOps.DATA_CHANGE, TrgOps.DATA_UPDATE, TrgOps.QUALITY_CHANGE);
                            set_op.setOptionalFields(OptFlds.REASON_FOR_INCLUSION, OptFlds.BUFFER_OVERFLOW, OptFlds.DATASET_NAME);
                            set_op.setReportEnabled(true);
                            monfox.stack.iec61850.api.client.BRCB.SetOp.Response rsp = set_op.perform();
                            if (rsp.isError()) {
                                throw new SCADAException(rsp.getError().name());
                            }
                            break;
                        } catch (ModelException me) {
                            throw me;
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new SCADAException(e);
        }
    }

    /**
     * 禁用模拟量自动上送
     *
     * @param client
     * @throws SCADAException
     */
    private static void disableBRCB(IEC61850Client client) throws SCADAException {
        try {
            for (LD ld : client.getLDs()) {
                List<BRCB> brcb_list = ld.getLLN0().getBRCBs();
                for (BRCB brcb : brcb_list) {
                    if (!brcb.isReportEnabled()) {
                        // -- not reserved, lets reserve this one
                        try {
                            BRCB.SetOp set_op = brcb.newSetOp();
                            set_op.setReportEnabled(false);
                            monfox.stack.iec61850.api.client.BRCB.SetOp.Response rsp = set_op.perform();
                            if (rsp.isError()) {
                                throw new SCADAException(rsp.getError().name());
                            }
                            break; // reserved okay, can stop iterating..
                        } catch (ModelException me) {
                            throw me;
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new SCADAException(e);
        }
    }

    /**
     * 启用数字量自动上送
     *
     * @param client
     * @throws SCADAException
     */
    private static void enableURCB(IEC61850Client client) throws SCADAException {
        try {
            for (LD ld : client.getLDs()) {
                List<URCB> urcb_list = ld.getLLN0().getURCBs();
                for (URCB urcb : urcb_list) {
                    if (!urcb.isReportEnabled()) {
                        URCB.SetOp set_op = urcb.newSetOp();
                        set_op.setBufferTime(1000);
                        set_op.setIntegrityPeriod(integrityPeroid);
                        set_op.setTriggerOptions(TrgOps.DATA_CHANGE, TrgOps.DATA_UPDATE, TrgOps.QUALITY_CHANGE, TrgOps.GENERAL_INTERROGATION, TrgOps.INTEGRITY);
                        set_op.setOptionalFields(OptFlds.REASON_FOR_INCLUSION, OptFlds.BUFFER_OVERFLOW, OptFlds.DATASET_NAME);
                        set_op.setReportEnabled(true);
                        monfox.stack.iec61850.api.client.URCB.SetOp.Response rsp = set_op.perform();
                        if (rsp.isError()) {
                            throw new SCADAException(rsp.getError().name());
                        }
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new SCADAException(e);
        }
    }

    /**
     * 禁用数字量自动上送
     *
     * @param client
     * @throws SCADAException
     */
    private static void disableURCB(IEC61850Client client) throws SCADAException {
        try {
            for (LD ld : client.getLDs()) {
                List<URCB> urcb_list = ld.getLLN0().getURCBs();
                for (URCB urcb : urcb_list) {
                    if (!urcb.isReportEnabled()) {
                        URCB.SetOp set_op = urcb.newSetOp();
                        set_op.setReportEnabled(false);
                        monfox.stack.iec61850.api.client.URCB.SetOp.Response rsp = set_op.perform();
                        if (rsp.isError()) {
                            throw new SCADAException(rsp.getError().name());
                        }
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new SCADAException(e);
        }
    }

    /**
     * @param aNode
     * @param client
     * @param result1
     * @throws ModelValueException
     * @throws ACSIServiceErrorException
     * @throws ModelServiceException
     * @throws SCADAException
     * @throws ModelCommunicationException
     */
    private static void read(String aNode, IEC61850Client client, Values result1) throws ModelValueException, ACSIServiceErrorException, SCADAException, ModelCommunicationException, ModelServiceException {
        ArrayList<Value> list = new ArrayList<Value>();
        String[] ss = aNode.split("/");
        if (ss.length < 2) return;
        ModelNode n = client.getLD(ss[0]).getChildForPath(ss[1]);
        if (n == null) {
            DataSet ds = client.getLD(ss[0]).getDataSet(ss[1]);
            GetOp.Response resp = ds.newGetOp().perform();
            if (resp.isSuccess()) {
                for (GetOp.AccessResult result : resp.getResults()) {
                    DataValue value = result.getValue();
                    list.add(Commands.dataValueString(value, result.getAttribute().getDataRef()));
                }
            } else {
                throw new SCADAException(resp.getError().toString());
            }
        } else if (n instanceof LN) {
            LN ln = (LN) n;
            monfox.stack.iec61850.api.client.DataNode.GetOp.Response resp = ln.newGetOp().perform();
            if (resp.isSuccess()) {
//                list.add(resp.getValue().toString());
            } else {
                throw new SCADAException(resp.getError().toString());
            }
        } else if (n instanceof DO) {
            DO d = (DO) n;
            monfox.stack.iec61850.api.client.DataNode.GetOp.Response resp = d.newGetOp().perform();
            if (resp.isSuccess()) {
                list.add(Commands.dataValueString(resp.getValue(), d.getObjectRef()));
            } else {
                throw new SCADAException(resp.getError().toString());
            }
        } else if (n instanceof DA) {
            DA d = (DA) n;
            monfox.stack.iec61850.api.client.DataNode.GetOp.Response resp = d.newGetOp().perform();
            if (resp.isSuccess()) {
                // list.add(resp.getValue().toString());
            } else {
                throw new SCADAException(resp.getError().toString());
            }
        }
        result1.setValues(list);
    }

    /**
     * 获取所有节点
     *
     * @param client
     * @param result1
     */
    private static void readAllDs(IEC61850Client client, Values result1) {
        ArrayList<Value> list = new ArrayList<Value>();
        try {
            for (LD ld : client.getLDs()) {
                for (DataSet ds : ld.getLLN0().getDataSets()) {
                    GetOp op = ds.newGetOp();
                    op.setTimeoutMillis(5000);
                    monfox.stack.iec61850.api.client.GetOp.Response resp = op.perform();
                    if (resp.isSuccess()) {
                        for (GetOp.AccessResult result : resp.getResults()) {
                            DataValue value = result.getValue();
                            list.add(Commands.dataValueString(value, result.getAttribute().getDataRef()));
                        }
                    } else {
                        System.out.println(resp.getError());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        result1.setValues(list);
    }
}
